使用成员函数的算法

有许多算法都是将某个函数应用于一个序列里的各个元素。例如,在3.8.4节

for_each(ii, eos, record);

对输入的每个串调用 record()

我们也经常需要处理指针的容器,而且实际希望的是对每个被指向的元素调用它的某个成员函数,而不是对指针去使用一个全局函数。例如,我们可能想对一个 list<Shape*> 里的每个元素调用成员函数 Shape::draw()。要处理这个特定例子,我们先简单写出一个非成员函数,让它去调用成员函数。例如,

    void draw(Shape* p)
    {
        p->draw();
    }

    void f(list<Shape*>& sh)
    {
        for_each(sh.begin(), sh.end(), draw);
    }

通过将这种技术加以推广,我们就可以按如下方式写出这个例子:

    void g(list<Shape*>& sh)
    {
        for_each(sh.begin(), sh.end(), mem_fun(&Shape::draw));   // #include <functional>
    }

标准库模版 mem_fun()(18.4.4.2节)以一个到成员函数的指针(15.5节)为参数,产生出某种东西,使它可以对某个指向该成员所在的类的指针调用。这里 mem_fun(&Shape::draw) 的结果就以 Shape* 为参数,返回的就是 Shape::draw() 返回的东西。

这种 mem_fun() 机制是非常重要的,因为它使各种标准算法能够被应用于保存多态对象的容器。


注(edit by shenjun)

    #include <iostream>
    #include <string>
    #include <typeinfo>
    using namespace std;

    class Foo
    {
        public:
            void foo(int a)
            { cout << a << endl; }

            static void bar(int a)
            { cout << a << endl; } 
    };

    int main(int argc, const char *argv[])
    {
    //veersion 1      
        //void (*pFunc)(int) = &Foo::foo;  //错误 ❌
        //Foo::foo 的形式参数有两个:一个隐式,一个int
        //void (*pFunc)(int)的形式参数只有一个
        // pFunc(123);

    //version 2    
        void (*pFunc)(int) = &Foo::bar;//ok
        pFunc(123);
        //这里表明:static成员函数的参数没有隐式参数(本对象)

    //修正1-->为其加一个参数即可    
        void (Foo::*pFunc2)(int) = &Foo::foo;
        Foo f;
        (f.*pFunc2)(12345);
        Foo *pf = &f ;
        (pf->*pFunc2)(123124);
        return 0;
    }

mem_fun适配器

    头文件:<functional>

既然 foo 含有一个隐式参数,那么能否将其转化出来呢?我们使用STL中的 mem_fun,这是一种函数适配器。

    Foo f;
    //void (Foo::*)(int)->void (*)(Foo*,int)
    (mem_fun(&Foo::foo))(&f,123);

mem_fun 的具体作用是一种转化作用,将 void (Foo::)(int) 类型的成员函数指针转化为 void (Foo, int),后者是一个自由函数类型的指针,可以像 static 成员函数那样自由调用。

🔚